// Copyright (c) 2021 Huawei Device Co., Ltd.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Autogenerated file -- DO NOT EDIT!
import * as ir from "./irnodes";

export const builtinsCodeMap = {
% PandaBuiltins::instructions.each do |instr|
%   sig = instr['sig']
%   args = sig.split(/,?\s+/)
%   args_len = args.length()
%   builtin_num_of_instr = 0;
    "<%= instr.mnemonic %>" : {
%   PandaBuiltins::builtins.each do |builtin|
%     if builtin.insn == instr.mnemonic
      "<%= builtin.mnemonic %>" : <%= builtin.id %>,
      <%= builtin.id %> : "<%= builtin.mnemonic %>",
%     end
%   end
    },
% end
};

% def insn2node(insn)
%   mnemonic = insn.mnemonic.split('.')
%   return mnemonic.map{|el| el == '64' ? 'Wide' : el.capitalize}.join()
% end

export class BuiltinExpander {
    static getSubCode(ins: ir.Intrinsic): number | undefined {
        for (let key in builtinsCodeMap) {
            let code = (builtinsCodeMap as any)[key][ins.mnemonic];
            if (code != undefined) {
                return code;
            }
        }
        return undefined;
    }

    static expand2Builtin(ins: ir.Intrinsic, operands: ir.OperandType[]) {
        let code = this.getSubCode(ins);
        if ((code == undefined) || (code >= 256)) {
            throw new Error("Intrinsic getSubCode subcode(" + ins.mnemonic + ") ir = " + ins.toString());
        }

        let codeImm = new ir.Imm(ir.ResultType.Int, code);
        let newNode;
        switch (ins.mnemonic) {
% PandaBuiltins::instructions.each do |instr|
%   sig = instr['sig']
%   args = sig.split(/,?\s+/)
%   args_len = args.length()
%   builtin_num_of_instr = 0;
%   PandaBuiltins::builtins.each do |builtin|
%     if builtin.insn == instr.mnemonic
%       builtin_num_of_instr += 1;
            case "<%= builtin.sig.split(' ')[0]%>":
%     end
%   end
%   if builtin_num_of_instr > 0
%     parameters = ""
%     for i in 2..args_len-1 # ignore first two opcode
%       if (args[i].start_with?("imm"))
                if (!(operands[<%= i-2%>] instanceof ir.Imm)) {
                    throw new Error("<%= i-2%> parameters must be Imm <" + ins.toString() + ">");
%         parameters += ", <ir.Imm>operands[" + (i-2).to_s + "]"
                }
%       elsif (args[i].start_with?("v"))
                if (!(operands[<%= i-2%>] instanceof ir.VReg)) {
                    throw new Error("<%= i-2%> parameters must be VReg <" + ins.toString() + ">");
%         parameters += ", <ir.VReg>operands[" + (i-2).to_s + "]"
                }
%       elsif (args[i].include?("string_id"))
                if (typeof(operands[<%= i-2%>]) != 'string') {
                    throw new Error("<%= i-2%> parameters must be string <" + ins.toString() + ">");
%         parameters += ", <string>operands[" + (i-2).to_s + "]"
                }
%       elsif (args[i].include?("method_id"))
                if (typeof(operands[<%= i-2%>]) != 'string') {
                    throw new Error("<%= i-2%> parameters must be string <" + ins.toString() + ">");
%         parameters += ", <string>operands[" + (i-2).to_s + "]"
                }
%       else
%         raise "Unknown parameters type"
%       end
%     end
%     if insn2node(instr) == "BuiltinR2i"
                let imm = <ir.Imm>operands[0];
                operands.shift();
                newNode = new ir.<%= insn2node(instr)%>(codeImm, imm, <ir.VReg[]>operands);
                break;
%     else
                newNode = new ir.<%= insn2node(instr)%>(codeImm<%= parameters%>);
                break;
%     end
%   end
% end
            default:
                throw new Error("Intrinsic can't found subcode(" + ins.mnemonic + ") ir = " + ins.toString());
        }

        return newNode;
    }
}
